package com.fosafer.idcard_demo.act;

import android.annotation.SuppressLint;
import android.content.Intent;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Handler;
import android.text.TextUtils;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import com.fosafer.idcard_demo.R;
import com.fosafer.idcard_demo.util.AppManagerUtil;
import com.fosafer.idcard_demo.util.ConstantsUtil;
import com.fosafer.idcard_demo.util.ImageUtils;
import com.fosafer.idcard_demo.util.MediaUtil;
import com.fosafer.idcard_demo.util.WorkingStatus;
import com.fosafer.lib.FOSAuthenticator;
import com.fosafer.lib.FOSError;
import com.fosafer.lib.FOSKeys;
import com.fosafer.lib.ui.view.CameraPreview;
import com.google.gson.Gson;

import org.json.JSONException;
import org.json.JSONObject;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


/**
 * Package:      [com.fosafer.idcard_demo.act]
 * ClassName:    [FaceVerifyAct]
 * Description:  [考勤]
 * Author:       [cuijianzhi]
 * CreateDate:   [2016/04/12 15:22]
 * UpdateUser:   [cuijianzhi]
 * UpdateDate:   [2016/04/12 15:22]
 * UpdateRemark: [Update Description]
 * Version:      [v1.0.0]
 * <p>
 * Copyright (c) 2016 Fosafer Co.,Ltd. All rights reserved.
 */
public class FaceVerifyAct extends BaseAct implements View.OnClickListener, SensorEventListener {

    //服务期地址，可选（已默认设置）
    private static final String SERVER = "https://id.fosafer.com/biology/v1/hdPhotoAuth";
    private static final String TERMINAL_ID = "8001700226";
    private static final String MEMBER_ID = "8001700226";
    private static final String CER_NAME = "fosafer_170724_pri.pfx";
    private static final String CER_PASSWORD = "999999";
    private boolean isStartKeepVertical = false;
    private long lastStartVerticalTime;
    private boolean mIsActivityCanceled = false;

    private static boolean isVertical = false;
    private static long lastVerticalTime;
    private Sensor mAccelerometer;
    private Sensor mMagneticField;
    private SensorManager mSensorManager;
    /**
     * 流程是否已经开始, 在流程开始后将不再处理人脸状态和竖直状态的回调
     */
    private boolean mIsInit = false;
    private boolean mIsStarted = false;
    private boolean isStartFaceDet = false;
    /**
     * 检测传感器数值, 让用户保持手机竖直状态
     */
    private float[] mGravity;
    private float[] mGeomagnetic;


    CameraPreview mCameraView;
    TextView act_face_verify_tv_tips;
    TextView layout_top_tv_left;
    ImageView mFaceOutline;
    private String mName;
    private String mIDCaRd;

    private FOSAuthenticator mAuthenticator;
    private WorkingStatus mWorkingStatus = WorkingStatus.Idle;
    private Handler mHandler = new Handler();
    private Handler mPlayHandler = new Handler();
    private MediaUtil mediaUtil;
    /**
     * 流程是否已经开始, 在流程开始后将不再处理人脸状态和竖直状态的回调
     */
    private boolean isKeep = false;
    private boolean isDetectedTimeout = false;
    private boolean isDetectedCancle = false;
    private FOSAuthenticator.FOSAuthenticatorListener
            mAuthenticatorListener = new FOSAuthenticator.FOSAuthenticatorListener() {
        @Override
        public void onReadyForAuthenticating() {
        }

        @Override
        public void onFaceStatusChanged(Map<String, Object> faceInfo) {
            doOnFaceStatusChanged(faceInfo);

        }

        @Override
        public void onEndOfCollecting() {
            Log.d("daize","onEndOfCollecting");
        }

        @Override
        public void onCollectedImages(List<byte[]> images) {
            Log.d("daize","onCollectedImages");
        }


        @Override
        public void onError(FOSError error) {
            disMissProgressDialog();
            finish();
        }

        @SuppressLint("HandlerLeak")
        @Override
        public void onFinish(Map<String, Object> result) {
            mHandler.removeCallbacksAndMessages(null);
            if (!isDetectedTimeout && !isDetectedCancle) {
                if (!mIsActivityCanceled) {
                    FOSError mError = (FOSError) result.get(FOSKeys.KEY_ERROR);
                    if (mError != null) {
                        disMissProgressDialog();
                        showTipDialog(getString(R.string.tips_verify_failed), mError.errorDescription, FaceVerifyAct.this);
                    } else {
                        try {
                            JSONObject resultJson = (JSONObject) result.get(FOSKeys.KEY_JSON_OBJECT);
                            Log.d("daize",new Gson().toJson(resultJson));
                            boolean success = resultJson.optBoolean(FOSKeys.KEY_SUCCESS);
                            if (success) {
                                JSONObject dataJson = resultJson.getJSONObject(FOSKeys.KEY_DATA);
                                if (FOSKeys.KEY_SUCCEED.equals(dataJson.optString(FOSKeys.KEY_CODE))) {
                                    showEnsureDialog(mContext, getString(R.string.tips), dataJson.optString(FOSKeys.KEY_DESC), FaceVerifyAct.this);
                                } else {
                                    showTipDialog(getString(R.string.tips), dataJson.optString(FOSKeys.KEY_DESC), FaceVerifyAct.this);
                                }
                            } else {
                                showTipDialog(getString(R.string.tips), resultJson.optString(FOSKeys.KEY_ERROR_MSG), FaceVerifyAct.this);
                            }
                        } catch (JSONException e) {
                            e.printStackTrace();
                            showTipDialog(getString(R.string.tips), new FOSError(FOSError.FOS_ERROR_BAD_JSON).errorDescription, FaceVerifyAct.this);
                        }
                    }
                } else {
                    finish();
                }
                disMissProgressDialog();
            }
        }
    };

    /**
     * 人脸状态改变业务.
     *
     * @param faceInfo faceInfo
     */
    private void doOnFaceStatusChanged(final Map<String, Object> faceInfo) {
        int faceCount = (Integer) faceInfo.get(FOSKeys.KEY_FACE_COUNT);
        if (isStartKeepVertical
                && faceCount > 0
                && (System.currentTimeMillis() - lastStartVerticalTime) > ConstantsUtil.TIME_800) {
            mHandler.removeCallbacksAndMessages(null);
            mFaceOutline.setImageBitmap(ImageUtils.readBitMap(R.drawable.face_light));
            if (mWorkingStatus == WorkingStatus.Working) {
                showProgressDialog();
                mWorkingStatus = WorkingStatus.Idle;
                mAuthenticator.finishWorking();
                mPlayHandler.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        mediaUtil.playStopSound();
                    }
                }, ConstantsUtil.TIME_80);
                act_face_verify_tv_tips.setVisibility(View.GONE);
                act_face_verify_tv_tips.setText("");
            }
        }
        if (isKeep) {
            return;
        }

        String tips = "";
        if (!isVertical) {
            //非垂直
            tips = getString(R.string.tips_vertical_phone);
            isStartKeepVertical = false;
        } else {
            if ((Boolean) faceInfo.get(FOSKeys.KEY_IS_DETECTED_FACE)) {
                //检测到人脸
                if ((int) faceInfo.get(FOSKeys.KEY_AREA_LARGE) == 0) {
                    tips += getString(R.string.tips_area_large);
                    isStartKeepVertical = false;
                } else if ((int) faceInfo.get(FOSKeys.KEY_AREA_SMALL) == 0) {
                    tips += getString(R.string.tips_area_small);
                    isStartKeepVertical = false;
                } else if ((int) faceInfo.get(FOSKeys.KEY_POSTURE) == 0) {
                    tips += getString(R.string.tips_posture);
                    isStartKeepVertical = false;
                } else if (!(Boolean) faceInfo.get(FOSKeys.KEY_IS_RANGE)) {
                    tips = getString(R.string.tips_rang);
                    isStartKeepVertical = false;
                } else if ((Boolean) faceInfo.get(FOSKeys.KEY_IS_MULTI_FACE)) {
                    tips = getString(R.string.tips_multi_face);
                    isStartKeepVertical = false;
                } else {
                    tips = getString(R.string.tips_keep);
                    if (!isStartKeepVertical) {
                        act_face_verify_tv_tips.setVisibility(View.VISIBLE);
                        act_face_verify_tv_tips.setText(tips);
                        isStartKeepVertical = true;
                        lastStartVerticalTime = System.currentTimeMillis();
                        mAuthenticator.clearImageCache();
                        isStartFaceDet = true;
                    } else {
                        long timeUsed = System.currentTimeMillis() - lastStartVerticalTime;
                        if (timeUsed > ConstantsUtil.TIME_1000) {
                            isKeep = true;
                            isStartKeepVertical = false;
                            isStartFaceDet = false;
                        }
                    }
                }
            } else {
                tips = getString(R.string.tips_rang);
                isStartKeepVertical = false;
            }

        }
        if (!TextUtils.isEmpty(tips)) {
            act_face_verify_tv_tips.setVisibility(View.VISIBLE);
            act_face_verify_tv_tips.setText(tips);
        } else {
            act_face_verify_tv_tips.setVisibility(View.GONE);
        }
    }


    @Override
    protected void initView() {
        super.initView();
        isDetectedCancle = false;
        mCameraView = (CameraPreview) findViewById(R.id.camera_view);
        act_face_verify_tv_tips = (TextView) findViewById(R.id.act_face_verify_tv_tips);
        layout_top_tv_left = (TextView) findViewById(R.id.layout_top_tv_left);
        mFaceOutline = (ImageView) findViewById(R.id.face_outline);
        Intent intent = getIntent();
        mName = intent.getStringExtra(FOSKeys.KEY_ID_HOLDER);
        mIDCaRd = intent.getStringExtra(FOSKeys.KEY_ID_CARD);

        mediaUtil = new MediaUtil(mContext, ConstantsUtil.FILE_TIP_STOP);
        layout_top_tv_left.setVisibility(View.VISIBLE);
        layout_top_tv_left.setCompoundDrawablesWithIntrinsicBounds(
                getResources().getDrawable(R.drawable.back),
                null, null, null);
        layout_top_tv_left.setOnClickListener(this);

        mSensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
        mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
        mMagneticField = mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);


    }

    @Override
    public void onClick(final View view) {
        switch (view.getId()) {
            case R.id.layout_top_tv_left:
                mIsActivityCanceled = true;
                finish();
                break;
            case R.id.layout_dialog_verify_ok_tv_ok:
                disEnsureDialog();
                AppManagerUtil.getInstance().finishAct("UserInfoAct");
                finish();
                break;
            case R.id.layout_dialog_small_tv_ok:
                disTipDialog();
                finish();
                break;
            case R.id.layout_dialog_small_tv_cancel:
                disTipDialog();
                AppManagerUtil.getInstance().finishAct("UserInfoAct");
                finish();
                break;
            default:
                break;
        }
    }

    /**
     * init FOSAuthenticator.
     */
    private void initAuthenticator() {
        showProgressDialog();
        isKeep = false;
        mIsInit = false;
        isVertical = false;
        mIsStarted = false;
        isStartFaceDet = false;
        isDetectedTimeout = false;
        isDetectedCancle = false;
        isStartKeepVertical = false;
        mFaceOutline.setImageBitmap(ImageUtils.readBitMap(R.drawable.face_white));
        mCameraView.showFaceObjects(false, false);
        mAuthenticator = new FOSAuthenticator(mContext, mCameraView, getFaceParams());
        mAuthenticator.setAuthenticatorListener(mAuthenticatorListener);
        mIsInit = true;
        mHandler.postDelayed(new Runnable() {
            @Override
            public void run() {
                timeOver();
            }
        }, ConstantsUtil.TIME_10000);
        disMissProgressDialog();

    }

    /**
     * 获取人脸认证参数.
     *
     * @return Map <String,Object>
     */
    private Map<String, Object> getFaceParams() {
        Log.d("daize","SERVER="+SERVER);
        Log.d("daize","TERMINAL_ID="+TERMINAL_ID);
        Log.d("daize","MEMBER_ID="+MEMBER_ID);
        Log.d("daize","CER_NAME="+CER_NAME);
        Log.d("daize","CER_PASSWORD="+CER_PASSWORD);
        Log.d("daize","mName="+mName);
        Log.d("daize","mIDCaRd="+mIDCaRd);
        Map<String, Object> mParams = new HashMap<>();
        //设置请求URL
        mParams.put(FOSKeys.KEY_SERVER, SERVER);
        //设置提供给商户的唯一终端号
        mParams.put(FOSKeys.KEY_TERMINAL_ID, TERMINAL_ID);
        //合作商户的唯一编号
        mParams.put(FOSKeys.KEY_MEMBER_ID, MEMBER_ID);
        //设置秘钥名称
        mParams.put(FOSKeys.KEY_CER_NAME, CER_NAME);
        //设置秘钥密码
        mParams.put(FOSKeys.KEY_CER_PASSWORD, CER_PASSWORD);
        //设置需要认证用的名字
        mParams.put(FOSKeys.KEY_ID_HOLDER, mName);
        //设置身份证号
        mParams.put(FOSKeys.KEY_ID_CARD, mIDCaRd);
        //设置交易时间
        mParams.put(FOSKeys.KEY_TRADE_DATE, new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()));
        //设置商户订单号
        mParams.put(FOSKeys.KEY_TRANS_ID, "" + System.currentTimeMillis());
        Log.d("daize",new Gson().toJson(mParams));
        return mParams;
    }

    @Override
    protected void onResume() {
        super.onResume();
        initAuthenticator();
        mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_UI);
        mSensorManager.registerListener(this, mMagneticField, SensorManager.SENSOR_DELAY_UI);

    }


    @Override
    protected void onPause() {
        super.onPause();
        isDetectedCancle = true;
        mSensorManager.unregisterListener(this);
        mHandler.removeCallbacksAndMessages(null);
        if (mWorkingStatus == WorkingStatus.Working) {
            mWorkingStatus = WorkingStatus.Idle;
            mAuthenticator.cancel();
            mAuthenticator = null;
        }
        // 界面Pause后退出
        if (!isDetectedTimeout) {
            finish();
        }
    }

    /**
     * 时间到.
     */
    private void timeOver() {
        showProgressDialog();
        isDetectedTimeout = true;
        mWorkingStatus = WorkingStatus.Idle;
        if (mAuthenticator != null) {
            mAuthenticator.cancel();
            mAuthenticator = null;
        }
        act_face_verify_tv_tips.setVisibility(View.GONE);
        act_face_verify_tv_tips.setText("");
        disMissProgressDialog();
        //条件不满足,跳转至超时页面
        skip(TimeOutAct.class, false);

    }


    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_BACK) {
            mIsActivityCanceled = true;
        }
        return super.onKeyDown(keyCode, event);
    }


    @Override
    protected void onDestroy() {
        super.onDestroy();

        mHandler.removeCallbacksAndMessages(null);
        if (mAuthenticatorListener != null) {
            mAuthenticatorListener = null;
        }
        if (mContext != null) {
            mContext = null;
        }
    }

    @Override
    public int getContentViewLayoutId() {
        return R.layout.act_face_verify;
    }

    @Override
    public void onSensorChanged(SensorEvent event) {
        if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
            mGravity = event.values;
        }
        if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD) {
            mGeomagnetic = event.values;
        }
        if (mGravity != null
                && mGeomagnetic != null
                && (System.currentTimeMillis() - lastVerticalTime) > ConstantsUtil.TIME_500) {
            lastVerticalTime = System.currentTimeMillis();
            float RArray[] = new float[9];
            float I[] = new float[9];
            boolean success = SensorManager.getRotationMatrix(RArray, I, mGravity, mGeomagnetic);
            if (success && mIsInit) {
                float orientation[] = new float[3];
                SensorManager.getOrientation(RArray, orientation);
                float pitch = orientation[1];
                if (pitch < -1.1f && pitch > -1.7f) {
                    isVertical = true;
                    if (!mIsStarted) {
                        if (mAuthenticator != null) {
                            if (mWorkingStatus == WorkingStatus.Idle) {
                                mWorkingStatus = WorkingStatus.Working;
                                mIsStarted = true;
                                mAuthenticator.startFaceWorking();
                            }
                        }
                    }
                } else if (!isKeep) {
                    isVertical = false;
                    if (!isStartFaceDet) {
                        act_face_verify_tv_tips.setVisibility(View.VISIBLE);
                        act_face_verify_tv_tips.setText(getString(R.string.tips_vertical_phone));
                    }
                }
            }
        }

    }

    @Override
    public void onAccuracyChanged(Sensor sensor, int accuracy) {

    }
}
